package com.vitogiovanni.tobook;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.app.Fragment;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
import android.os.AsyncTask.Status;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListView;
import android.widget.TextView;

import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.vitogiovanni.tobook.entity.servizioendpoint.Servizioendpoint;
import com.vitogiovanni.tobook.entity.servizioendpoint.model.CollectionResponseServizio;
import com.vitogiovanni.tobook.entity.servizioendpoint.model.Servizio;
import com.vitogiovanni.tobook.entity.tipologialocaleendpoint.Tipologialocaleendpoint;
import com.vitogiovanni.tobook.entity.tipologialocaleendpoint.model.CollectionResponseTipologiaLocale;
import com.vitogiovanni.tobook.entity.tipologialocaleendpoint.model.TipologiaLocale;
import com.vitogiovanni.tobook.utilities.NetworkChecker;
import com.vitogiovanni.tobook.utilities.ServizioTaskCompleteListener;
import com.vitogiovanni.tobook.utilities.TipologiaTaskCompleteListener;

public class RicercaLocaliActivity extends BaseActivity implements
		ServizioTaskCompleteListener<List<Servizio>>,
		TipologiaTaskCompleteListener<List<TipologiaLocale>> {
	
	private static final String LOG_TAG = "ExampleApp";

	private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place";
	private static final String TYPE_AUTOCOMPLETE = "/autocomplete";
	private static final String OUT_JSON = "/json";
	
	private static final String API_KEY = "AIzaSyDD8xSJF-sP8pW86KvmE_qWo_aGvHF4pmQ";
	private ServizioTask serviziotask = null;
	private TipologiaTask tipologiatask = null;
	
	private ProgressDialog progressDialogServizi;
	private ProgressDialog progressDialogTipologie;
	
	private boolean wantServizi, wantTipologie;
	
	private List<Servizio> listServizi;
	private boolean[] selectedServizi;
	
	private List<TipologiaLocale> listTipologie;
	private boolean[] selectedTipologie;

	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_ricerca_locali);
		
		wantServizi = false;
		wantTipologie = false;
		AutoCompleteTextView autoCompView = (AutoCompleteTextView) findViewById(R.id.autocompletelocalita);
		autoCompView.setAdapter(new PlacesAutoCompleteAdapter(this, R.layout.list_item));
		tipologiatask = (TipologiaTask) new TipologiaTask(this,this).execute();
		serviziotask = (ServizioTask) new ServizioTask(this,this).execute();	

	}
	
	@Override
	protected void onStop()  {
		super.onStop();
		if(serviziotask != null)
		{
			serviziotask.cancel(true);
		}
		if(tipologiatask != null)
		{
			tipologiatask.cancel(true);
		}
	}	

	/** Called when user click on button scelta_tipologia */
	public void sceltaTipologia(View view) {
		if (!NetworkChecker.isInternetAvailable(RicercaLocaliActivity.this)) {
			NetworkChecker.noConnectionToast(RicercaLocaliActivity.this);
			return;
		}
		wantTipologie = true;
		if (tipologiatask == null) {
			selectedTipologie = null;
			tipologiatask = (TipologiaTask) new TipologiaTask(this, this)
					.execute();
			progressDialogTipologie = createTipologiaProgressDialog();
			progressDialogTipologie.show();

		} else if (tipologiatask.getStatus().equals(Status.FINISHED)) {
			try {
				onTipologiaTaskComplete(tipologiatask.get());
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			}

		} else {
			progressDialogTipologie = createTipologiaProgressDialog();
			progressDialogTipologie.show();
		}
	}
	
	/** Called when user click on button scelta_servizi */
	public void sceltaServizi(View view) {	
		if (!NetworkChecker.isInternetAvailable(RicercaLocaliActivity.this)) {
			NetworkChecker.noConnectionToast(RicercaLocaliActivity.this);
			return;
		}
		wantServizi = true;
		if(serviziotask == null)
		{
			selectedServizi = null;
			serviziotask = (ServizioTask) new ServizioTask(this,this).execute();
			progressDialogServizi = createServizioProgressDialog();
			progressDialogServizi.show();
		}
		else if(serviziotask.getStatus().equals(Status.FINISHED))
		{
			try {
				onServizioTaskComplete(serviziotask.get());
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			}
		}
		else
		{
			progressDialogServizi = createServizioProgressDialog();
			progressDialogServizi.show();
		}
		
	}
	
	/** Called when user click on button submit_ricerca */ 
	public void submitRicerca(View view){
		if (!NetworkChecker.isInternetAvailable(RicercaLocaliActivity.this)) {
			NetworkChecker.noConnectionToast(RicercaLocaliActivity.this);
			return;
		}
		Intent intent = new Intent(this, ListaLocaliActivity.class);
		
		// Coordinate da stringa ricerca (double x, double y)
		double coordinateX;
		double coordinateY;
		String address = ((AutoCompleteTextView)findViewById(R.id.autocompletelocalita)).getText().toString();
		if(!(address.equals("")))
		{
			Address location;
			location = getStringCoordinates(address);
			coordinateX = location.getLongitude();
			coordinateY = location.getLatitude();
			intent.putExtra("coordinataX", coordinateX);
			intent.putExtra("coordinataY", coordinateY);
			
			Log.i("coordinate" ,"coordinata X: " + Double.toString(coordinateX) + " coordinata Y: " + Double.toString(coordinateY) );
		}
		// Se non è stato selezionato un posto coordinateX e coordinateY saranno null
		
		
		// Servizi nel locale (long id)
		int k = 0;

		if (listServizi != null) {
			for (int j = 0; j < selectedServizi.length; j++) {
				if (selectedServizi[j]) {
					k++;
				}
			}
			if (k > 0) {
				List<String> serviziArray = new ArrayList<String>();
				int j = 0;
				for (Servizio serv : listServizi) {
					if (selectedServizi[j]) {
						serviziArray.add(serv.getId().getName());	
					}
					j++;
				}
				intent.putStringArrayListExtra("servizi", (ArrayList<String>) serviziArray);
			}
		}
		// Tipologie locali (long id)
		k = 0;
		if (listTipologie != null) {
			for(int j=0; j<selectedTipologie.length; j++)
			{
				if(selectedTipologie[j])
				{
					k++;
				}
			}
			if (k > 0) {
				List<String> tipologieArray = new ArrayList<String>();
				int j=0;
				for (TipologiaLocale tipol : listTipologie) {
					if (selectedTipologie[j]) {
						tipologieArray.add(tipol.getId().getName());
					}
					j++;
				}
				intent.putStringArrayListExtra("tipologie", (ArrayList<String>) tipologieArray);
			}

		}
		startActivity(intent);
		
	 }
	
	public void onTipologiaTaskComplete(List<TipologiaLocale> listTipologie) {
		wantTipologie = false;
		this.listTipologie = listTipologie;
		List<String> listItems = new ArrayList<String>();
		for(TipologiaLocale tipo: listTipologie)
	     {
	    	 listItems.add(tipo.getNome());
	     }
		 final CharSequence[] items = listItems.toArray(new CharSequence[listItems.size()]);
		 if(selectedTipologie == null)
		 {
			 selectedTipologie = new boolean[listItems.size()];
			 for(int i=0; i<selectedTipologie.length; i++)
			 {
				 selectedTipologie[i] = true;
			 }
		 }
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
	        builder.setTitle("Scegli la tipologia locale")
	        .setMultiChoiceItems(items, selectedTipologie,
	                new DialogInterface.OnMultiChoiceClickListener() {
	            @Override
	            public void onClick(DialogInterface dialog, int which,
	                    boolean isChecked) {
	            }
	        }).setPositiveButton("OK", new DialogInterface.OnClickListener() {
	            public void onClick(DialogInterface dialog, int which) {
	                //reading content of the dialog
	                AlertDialog a = ((AlertDialog)dialog);
	                boolean atLeastOneFalse = false;
	                String stringTipologie = "";
	                ListView lw = a.getListView();
	                SparseBooleanArray checked = lw.getCheckedItemPositions();
	                
	                for (int i = 0; i < selectedTipologie.length; i++) {
	                    if (checked.get(i)) {
	                        selectedTipologie[i] = true;
	                        if(!stringTipologie.equals(""))
	                        {
	                        	stringTipologie = stringTipologie.concat(", "); 
	                        }
	                        String tipologiastring = lw.getAdapter().getItem(i).toString();
	                        stringTipologie = stringTipologie.concat(tipologiastring);
	                    }
	                    else
	                    {
	                    	selectedTipologie[i] = false;
	                    	atLeastOneFalse = true;
	                    }
	                                       
	                }
	                if(!atLeastOneFalse)
                    {
                    	stringTipologie = getString(R.string.qualsiasi_tipologia);
                    }	
	                TextView tv = (TextView) findViewById(R.id.tipologia_content);
	                tv.setText(stringTipologie);
	            }
	        });
	        final AlertDialog alert3 = builder.create();
	        alert3.show();
	}
	
	public void onServizioTaskComplete(List<Servizio> listServizi) {
		 wantServizi = false;
		 this.listServizi = listServizi;
	     List<String> listItems = new ArrayList<String>();
	     for(Servizio serv: listServizi)
	     {
	    	 listItems.add(serv.getNome());
	     }
		 final CharSequence[] items = listItems.toArray(new CharSequence[listItems.size()]);
		 if(selectedServizi == null)
		 {
			 selectedServizi = new boolean[listItems.size()];
		 }
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
	        builder.setTitle("Scegli i servizi")
	        .setMultiChoiceItems(items, selectedServizi,
	                new DialogInterface.OnMultiChoiceClickListener() {
	            @Override
	            public void onClick(DialogInterface dialog, int which,
	                    boolean isChecked) {
	            }
	        }).setPositiveButton("OK", new DialogInterface.OnClickListener() {
	            @Override
	            public void onClick(DialogInterface dialog, int which) {
	                //reading content of the dialog
	                AlertDialog a = ((AlertDialog)dialog);
	                String stringServizi = "";
	                boolean atLeastOneTrue = false;
	                ListView lw = a.getListView();
	                SparseBooleanArray checked = lw.getCheckedItemPositions();
	                for (int i = 0; i < selectedServizi.length; i++) {
	                    if (checked.get(i)) {
	                    	atLeastOneTrue = true;
	                        selectedServizi[i] = true;
	                        if(!stringServizi.equals(""))
	                        {
	                        	stringServizi = stringServizi.concat(", "); 
	                        }
	                        stringServizi = stringServizi.concat(lw.getAdapter().getItem(i).toString());
	                    }else
	                    {
	                    	selectedServizi[i] = false;     
	                    }
	                }
	                if(!atLeastOneTrue)
	                {
	                	stringServizi = getString(R.string.nessuna_preferenza);
	                }
	                
	                	TextView tv = (TextView) findViewById(R.id.servizi_content);
	                	tv.setText(stringServizi);
	            }
	        });
	 
	        final AlertDialog alert3 = builder.create();
	        alert3.show();
	        
	    }
	 
		/**
	 * A placeholder fragment containing a simple view.
	 */
	public static class PlaceholderFragment extends Fragment {

		public PlaceholderFragment() {
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			View rootView = inflater.inflate(R.layout.fragment_ricerca_locali,
					container, false);
			return rootView;
		}
	}
	private ProgressDialog createTipologiaProgressDialog()
	{
		return ProgressDialog.show(
				RicercaLocaliActivity.this, "", "Caricamento in corso",
				true, true, new OnCancelListener() {
					public void onCancel(DialogInterface dialog) {
						wantTipologie = false;
						/*if (tipologiatask != null
								&& !tipologiatask.getStatus().equals(
										Status.FINISHED)) {
							tipologiatask.cancel(true);
							tipologiatask = null;
						}*/
					}
				});
	}
	private ProgressDialog createServizioProgressDialog()
	{
		return ProgressDialog.show(
				RicercaLocaliActivity.this, "", "Caricamento in corso",
				true, true, new OnCancelListener() {
					public void onCancel(DialogInterface dialog) {
						wantServizi = false;
						/*if (serviziotask != null
								&& !serviziotask.getStatus().equals(
										Status.FINISHED)) {
							serviziotask.cancel(true);
							serviziotask = null;
						}*/
					}
				});
	}
	private ArrayList<String> autocomplete(String input) {
	    ArrayList<String> resultList = null;

	    HttpURLConnection conn = null;
	    StringBuilder jsonResults = new StringBuilder();
	    try {
	        StringBuilder sb = new StringBuilder(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON);
	        sb.append("?sensor=false&key=" + API_KEY);
	        sb.append("&components=country:it");
	        sb.append("&input=" + URLEncoder.encode(input, "utf8"));

	        URL url = new URL(sb.toString());
	        conn = (HttpURLConnection) url.openConnection();
	        InputStreamReader in = new InputStreamReader(conn.getInputStream());

	        // Load the results into a StringBuilder
	        int read;
	        char[] buff = new char[1024];
	        while ((read = in.read(buff)) != -1) {
	            jsonResults.append(buff, 0, read);
	        }
	    } catch (MalformedURLException e) {
	        Log.e(LOG_TAG, "Error processing Places API URL", e);
	        return resultList;
	    } catch (IOException e) {
	        Log.e(LOG_TAG, "Error connecting to Places API", e);
	        return resultList;
	    } finally {
	        if (conn != null) {
	            conn.disconnect();
	        }
	    }

	    try {
	        // Create a JSON object hierarchy from the results
	        JSONObject jsonObj = new JSONObject(jsonResults.toString());
	        JSONArray predsJsonArray = jsonObj.getJSONArray("predictions");

	        // Extract the Place descriptions from the results
	        resultList = new ArrayList<String>(predsJsonArray.length());
	        for (int i = 0; i < predsJsonArray.length(); i++) {
	            resultList.add(predsJsonArray.getJSONObject(i).getString("description"));
	        }
	    } catch (JSONException e) {
	        Log.e(LOG_TAG, "Cannot process JSON results", e);
	    }

	    return resultList;
	}

	//Utility class
	
	private Address getStringCoordinates (String address)
	{
		List<Address> foundGeocode = null;
		Address location;
		/* find the addresses  by using getFromLocationName() method with the given address*/
		try {
			foundGeocode = new Geocoder(this).getFromLocationName(address, 1);
		} catch (IOException e) {
			e.printStackTrace();
		}
		location = foundGeocode.get(0);
		
		return location;
	}

	private class PlacesAutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
	    private ArrayList<String> resultList;

	    public PlacesAutoCompleteAdapter(Context context, int textViewResourceId) {
	        super(context, textViewResourceId);
	    }

	    @Override
	    public int getCount() {
	        return resultList.size();
	    }

	    @Override
	    public String getItem(int index) {
	        return resultList.get(index);
	    }

	    @Override
	    public Filter getFilter() {
	        Filter filter = new Filter() {
	            @Override
	            protected FilterResults performFiltering(CharSequence constraint) {
	                FilterResults filterResults = new FilterResults();
	                if (constraint != null) {
	                    // Retrieve the autocomplete results.
	                    resultList = autocomplete(constraint.toString());

	                    // Assign the data to the FilterResults
	                    filterResults.values = resultList;
	                    filterResults.count = resultList.size();
	                }
	                return filterResults;
	            }

	            @Override
	            protected void publishResults(CharSequence constraint, FilterResults results) {
	                if (results != null && results.count > 0) {
	                    notifyDataSetChanged();
	                }
	                else {
	                    notifyDataSetInvalidated();
	                }
	            }};
	        return filter;
	    }
	}
	
	private class ServizioTask extends AsyncTask<Void, Void, List<Servizio>>
	{
		private ServizioTaskCompleteListener<List<Servizio>> callback;
		
		public ServizioTask(Context context, ServizioTaskCompleteListener<List<Servizio>> cb)
		{
			this.callback = cb;
		}
		
		@Override
		protected List<Servizio> doInBackground(Void... arg0) {
			
			Servizioendpoint.Builder builder1 = new Servizioendpoint.Builder(
					AndroidHttp.newCompatibleTransport(), new JacksonFactory(),
					null);
			builder1 = CloudEndpointUtils.updateBuilder(builder1);
			builder1.setApplicationName("to-book");
			Servizioendpoint servizioEndpoint = builder1.build();
			List<Servizio> servizi = new ArrayList<Servizio>();
			try{
				CollectionResponseServizio serviziColl = servizioEndpoint.listServizio().execute();
				servizi = serviziColl.getItems();
			}catch(IOException e){
				e.printStackTrace();
			}

			return servizi;
			
		}
		
		@Override
		protected void onPostExecute(List<Servizio> result) {
			if (progressDialogServizi != null) 
			{
				progressDialogServizi.dismiss();
			}
			if (wantServizi)
			{
				callback.onServizioTaskComplete(result);
			}
		}
		
	}
	
	private class TipologiaTask extends AsyncTask<Void, Void, List<TipologiaLocale>>
	{
		private TipologiaTaskCompleteListener<List<TipologiaLocale>> callback;
		
		public TipologiaTask(Context context, TipologiaTaskCompleteListener<List<TipologiaLocale>> cb)
		{
			this.callback = cb;
		}
		
		@Override
		protected List<TipologiaLocale> doInBackground(Void... arg0) {
			
			Tipologialocaleendpoint.Builder builder1 = new Tipologialocaleendpoint.Builder(
					AndroidHttp.newCompatibleTransport(), new JacksonFactory(),
					null);
			builder1 = CloudEndpointUtils.updateBuilder(builder1);
			builder1.setApplicationName("to-book");
			Tipologialocaleendpoint tipologiaEndpoint = builder1.build();
			List<TipologiaLocale> tipologie = new ArrayList<TipologiaLocale>();
			try{
				CollectionResponseTipologiaLocale tipologieColl = tipologiaEndpoint.listTipologiaLocale().execute();
				tipologie = tipologieColl.getItems();
			}catch(IOException e){
				e.printStackTrace();
			}

			return tipologie;
			
		}
		
		@Override
		protected void onPostExecute(List<TipologiaLocale> result) {
			if (progressDialogTipologie != null) 
			{
				progressDialogTipologie.dismiss();
			}
			if (wantTipologie)
			{
				callback.onTipologiaTaskComplete(result);
			}
		}
		
	}
	
	@Override
	public void onBackPressed(){
		super.onBackPressed();
		
		Intent homeIntent = new Intent(RicercaLocaliActivity.this, MainActivity.class);
		homeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		startActivity(homeIntent);
	}
	
}
